package com.book.web.controller.app;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.book.common.annotation.RepeatSubmit;
import com.book.common.annotation.group.InsertGroup;
import com.book.common.annotation.group.UpdateGroup;
import com.book.common.core.controller.BaseController;
import com.book.common.core.domain.AjaxResult;
import com.book.common.core.domain.entity.AppUser;
import com.book.common.core.domain.model.AppLoginUser;
import com.book.common.core.page.TableDataInfo;
import com.book.common.utils.DateUtils;
import com.book.common.utils.SecurityUtils;
import com.book.common.utils.StringUtils;
import com.book.framework.manager.AsyncManager;
import com.book.framework.manager.factory.AsyncFactory;
import com.book.framework.web.service.TokenService;
import com.book.system.domain.*;
import com.book.system.domain.param.GoldCoinExchangeParam;
import com.book.system.domain.vo.AppUserVo;
import com.book.system.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.sql.Date;
import java.time.LocalDate;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Bigboss
 * @create 2024-11-10 13:54
 */
@Api(tags = "app用户统一业务层")
@RestController
@RequestMapping("/app/user")
public class AppUserController extends BaseController {

    private final IAppUserService appUserService;

    private final IFeedBackService feedBackService;

    private final IFollowersService followersService;

    private final IBookService bookService;

    private final ICommentService commentService;

    private final ITaskService taskService;

    private final IUserTaskCompletionService userTaskCompletionService;

    private final TokenService tokenService;

    private final IBookChapterService bookChapterService;

    private final IBrowsingHistoryService browsingHistoryService;

    private final IBookCategoryService bookCategoryService;

    private final ICarouselService carouselService;

    private final IBookShelfService bookShelfService;

    public AppUserController(IAppUserService appUserService, IFeedBackService feedBackService, IFollowersService followersService, IBookService bookService, ICommentService commentService, ITaskService taskService, IUserTaskCompletionService userTaskCompletionService, TokenService tokenService, IBookChapterService bookChapterService, IBrowsingHistoryService browsingHistoryService, IBookCategoryService bookCategoryService, ICarouselService carouselService, IBookShelfService bookShelfService) {
        this.appUserService = appUserService;
        this.feedBackService = feedBackService;
        this.followersService = followersService;
        this.bookService = bookService;
        this.commentService = commentService;
        this.taskService = taskService;
        this.userTaskCompletionService = userTaskCompletionService;
        this.tokenService = tokenService;
        this.bookChapterService = bookChapterService;
        this.browsingHistoryService = browsingHistoryService;
        this.bookCategoryService = bookCategoryService;
        this.carouselService = carouselService;
        this.bookShelfService = bookShelfService;
    }

    /**
     * 修改用户个人信息
     */
    @ApiOperation(value = "修改用户个人信息,只需传入avatar，nickName以及name即可")
    @PutMapping("/updateInfo")
    public AjaxResult updateProfile(@RequestBody AppUser user)
    {
        AppLoginUser loginUser = SecurityUtils.getAppLoginUser();
        AppUser currentUser = loginUser.getUser();
        currentUser.setNickName(user.getNickName());
        currentUser.setName(user.getName());
        currentUser.setAvatar(user.getAvatar());

        if (appUserService.updateById(currentUser))
        {
            // 更新缓存用户信息
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改个人信息异常，请联系管理员");
    }

    /**
     * 用户反馈
     *
     * @param feedBack
     * @return
     */
    @ApiOperation(value = "用户反馈")
    @RepeatSubmit
    @PostMapping("/addFeedBack")
    public AjaxResult addFeedBack(@RequestBody @Validated({InsertGroup.class}) FeedBack feedBack) {
        feedBack.setAppUserId(SecurityUtils.getAppUserId());
        feedBack.setCreateBy(SecurityUtils.getAppUsername());
        feedBack.setCreateTime(DateUtils.getNowDate());
        return success(feedBackService.save(feedBack));
    }


    /**
     * 关注
     *
     * @param followers
     * @return
     */
    @ApiOperation(value = "关注")
    @RepeatSubmit
    @PostMapping("/follow")
    public AjaxResult follow(@RequestBody @Validated({InsertGroup.class}) Followers followers) {
        //判断是否已经关注了
        Followers dbData = followersService.getOne(new LambdaQueryWrapper<Followers>()
                .eq(Followers::getFollower, SecurityUtils.getAppUserId())
                .eq(Followers::getFollowedPerson, followers.getFollowedPerson())
                .last("LIMIT 1"));
        if (ObjectUtil.isNotNull(dbData)) {
            return error("已经关注过了");
        }
        //开始关注
        followers.setFollower(SecurityUtils.getAppUserId());
        followers.setCreateBy(SecurityUtils.getAppUsername());
        followers.setCreateTime(DateUtils.getNowDate());
        return success(followersService.save(followers));
    }


    /**
     * 取消关注
     *
     * @param followers
     * @return
     */
    @ApiOperation(value = "取消关注")
    @RepeatSubmit
    @PutMapping("/unFollow")
    public AjaxResult unFollow(@RequestBody @Validated({UpdateGroup.class}) Followers followers) {
        boolean bool = followersService.remove(new LambdaQueryWrapper<Followers>()
                .eq(Followers::getFollower, SecurityUtils.getAppUserId())
                .eq(Followers::getFollowedPerson, followers.getFollowedPerson()));
        return toAjax(bool);
    }


    /**
     * 查询粉丝列表
     *
     * @return
     */
    @ApiOperation(value = "查询粉丝列表")
    @GetMapping("/getMyFollowers")
    public TableDataInfo getMyFollowers() {
        startPage();
        List<Followers> list = followersService.list(new LambdaQueryWrapper<Followers>()
                .eq(Followers::getFollowedPerson, SecurityUtils.getAppUserId())
                .orderByDesc(Followers::getCreateTime));
        if (ObjectUtil.isEmpty(list)) {
            return getDataTable(Collections.EMPTY_LIST);
        }
        //查询对应的粉丝用户信息
        List<String> followerIds = list.stream().map(Followers::getFollower).distinct().collect(Collectors.toList());
        List<AppUser> appUsers = appUserService.listByIds(followerIds);
        List<AppUserVo> appUserVos = BeanUtil.copyToList(appUsers, AppUserVo.class);
        Map<String, AppUserVo> userMap = appUserVos.stream().collect(Collectors.toMap(AppUserVo::getId, Function.identity()));
        list.forEach(followers -> followers.setFollowerUser(userMap.get(followers.getFollower())));

        return getDataTable(list);
    }


    /**
     * 查询热门推荐的书籍
     * @return
     */
    @ApiOperation("查询热门推荐的书籍")
    @GetMapping("/getHotBooks")
    public AjaxResult getHotBooks(){
        return success(bookService.list(new LambdaQueryWrapper<Book>()
                .eq(Book::getIsPopular, "1")
                .orderByDesc(Book::getCreateTime)));
    }

    /**
     * 查询我的评论
     * @return
     */
    @ApiOperation(value = "查询我的评论")
    @GetMapping("/getMyComments")
    public TableDataInfo getMyComments(){
        startPage();
        List<Comment> list = commentService.list(new LambdaQueryWrapper<Comment>()
                .eq(Comment::getAppUserId, SecurityUtils.getAppUserId())
                .orderByDesc(Comment::getCreateTime));
        if(ObjectUtil.isEmpty(list)){
            return getDataTable(Collections.EMPTY_LIST);
        }
        List<String> bookIds = list.stream().map(Comment::getBookId).distinct().collect(Collectors.toList());
        List<Book> books = bookService.listByIds(bookIds);
        Map<String, Book> bookMap = books.stream().collect(Collectors.toMap(Book::getId, Function.identity()));
        list.stream().forEach(item -> item.setBook(bookMap.getOrDefault(item.getBookId(),null)));
        return getDataTable(list);
    }

    /**
     * 评论
     * @param comment
     * @return
     */
    @ApiOperation(value = "评论")
    @RepeatSubmit
    @PostMapping("/addComment")
    public AjaxResult addComment(@RequestBody @Validated(InsertGroup.class) Comment comment){
    	//1。判断书籍是否存在
        Book book = bookService.getById(comment.getBookId());
        if(ObjectUtil.isNull(book)){
            return error("书籍不存在");
        }
        //2.开始评论
        comment.setAppUserId(SecurityUtils.getAppUserId());
        comment.setCreateBy(SecurityUtils.getAppUsername());
        comment.setCreateTime(DateUtils.getNowDate());
    	return toAjax(commentService.save(comment));
    }


    /**
     * 用户删除评论
     * @param id
     * @return
     */
    @ApiOperation(value = "用户删除评论")
    @DeleteMapping("/delComment/{id}")
    public AjaxResult delComment(@PathVariable("id") String id){
        boolean bool = commentService.remove(new LambdaQueryWrapper<Comment>()
                .eq(Comment::getId, id)
                .eq(Comment::getAppUserId, SecurityUtils.getAppUserId()));
        return toAjax(bool);
    }



    /**
     * 获取任务列表
     * @return
     */
    @ApiOperation(value = "获取任务列表")
    @GetMapping("/taskList")
    public AjaxResult taskList()
    {
        return success(taskService.list(new LambdaQueryWrapper<Task>().orderByAsc(Task::getCreateTime)));
    }


    /**
     * 用户完成任务
     * @param entity
     * @return
     */
    @ApiOperation("用户完成任务")
    @RepeatSubmit
    @PostMapping("/completionTask")
    public AjaxResult completionTask(@RequestBody @Validated({InsertGroup.class }) UserTaskCompletion entity){
        //1.判断用户今天是否已经完成过改为任务了
        UserTaskCompletion dbData = userTaskCompletionService.getOne(new LambdaQueryWrapper<UserTaskCompletion>()
                .eq(UserTaskCompletion::getAppUserId, SecurityUtils.getAppUserId())
                .eq(UserTaskCompletion::getTaskId, entity.getTaskId())
                .eq(UserTaskCompletion::getCompletionDate, LocalDate.now())
                .last("LIMIT 1"));
        if(ObjectUtil.isNotNull(dbData)){
            return error("该任务今天已经完成过了");
        }
        //2.判断任务是否存在
        Task task = taskService.getById(entity.getTaskId());
        if(ObjectUtil.isNull(task)){
            return error("任务不存在");
        }
        //3.开始完成操作
        entity.setAppUserId(SecurityUtils.getAppUserId());
        entity.setCompletionDate(Date.valueOf(LocalDate.now()));
        entity.setRewardEarned(task.getTaskReward());
        entity.setCreateBy(SecurityUtils.getAppUsername());
        entity.setCreateTime(DateUtils.getNowDate());
        return toAjax(userTaskCompletionService.completionTask(entity));
    }


    /**
     * 查询书籍列表
     * @return
     */
    @ApiOperation("查询书籍列表")
    @GetMapping("/bookList")
    public AjaxResult bookList(Book book){
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<Book>().orderByDesc(Book::getCreateTime);
        if(StringUtils.isNotEmpty(book.getCategoryId())){
            queryWrapper.eq(Book::getCategoryId,book.getCategoryId());
        }
        if(StringUtils.isNotEmpty(book.getBookName())){
            queryWrapper.like(Book::getBookName,book.getBookName());
        }
        queryWrapper.orderByDesc(Book::getCreateTime);
        List<Book> list = bookService.list(queryWrapper);
        if(ObjectUtil.isEmpty(list)){
            return success(Collections.EMPTY_LIST);
        }
        List<String> categoryIds = list.stream().map(Book::getCategoryId).distinct().collect(Collectors.toList());
        List<BookCategory> bookCategories = bookCategoryService.listByIds(categoryIds);
        Map<String, BookCategory> categoryMap = bookCategories.stream().collect(Collectors.toMap(BookCategory::getId, Function.identity()));
        list.stream().forEach(item -> item.setCategory(categoryMap.getOrDefault(item.getCategoryId(),null)));
        return success(list);
    }




    /**
     * 查询书籍分类列表
     * @return
     */
    @ApiOperation("查询书籍分类列表")
    @GetMapping("/categoryList")
    public AjaxResult categoryList(){
        List<BookCategory> categoryList = bookCategoryService.list(new LambdaQueryWrapper<BookCategory>()
                .orderByAsc(BookCategory::getCategorySort));
        if(ObjectUtil.isEmpty(categoryList)){
            return success(Collections.EMPTY_LIST);
        }
        List<String> categoryIdList = categoryList.stream().map(BookCategory::getId).distinct().collect(Collectors.toList());
        List<Book> bookList = bookService.list(new LambdaQueryWrapper<Book>().in(Book::getCategoryId,categoryIdList));
        Map<String, List<Book>> map = bookList.stream().collect(Collectors.groupingBy(Book::getCategoryId));
        categoryList.stream().forEach(item -> item.setBookList(map.getOrDefault(item.getId(),Collections.EMPTY_LIST)));
        return success(categoryList);
    }

    /**
     * 查询轮播图列表
     * @return
     */
    @ApiOperation("查询轮播图列表")
    @GetMapping("/carouselList")
    public AjaxResult carouselList(){
    	return success(carouselService.list(new LambdaQueryWrapper<Carousel>()
                .orderByAsc(Carousel::getSort)));
    }


    /**
     * 获取书籍详情
     * @param bookId
     * @return
     */
    @ApiOperation(value = "获取书籍详情")
    @GetMapping("/getBookInfo/{bookId}")
    public AjaxResult getBookInfo(@PathVariable("bookId") String bookId){
        Book book = bookService.getById(bookId);
        Map<String,Object> result  = new LinkedHashMap<>(2);

        if(ObjectUtil.isNull(book)){
            return error("书籍信息不存在");
        }
        //设置分类信息
        book.setCategory(bookCategoryService.getById(book.getCategoryId()));
        //查询是否加入了书架
        BookShelf shelf = bookShelfService.getOne(new LambdaQueryWrapper<BookShelf>()
                .eq(BookShelf::getAppUserId, SecurityUtils.getAppUserId())
                .eq(BookShelf::getBookId, bookId)
                .last("LIMIT 1"));
        book.setAddToShelf(ObjectUtil.isNotNull(shelf));
        //获取书籍的章节信息
        List<BookChapter> chapterList = bookChapterService.list(new LambdaQueryWrapper<BookChapter>()
                .eq(BookChapter::getBookId, bookId)
                .orderByAsc(BookChapter::getChapter));
        result.put("book",book);
        result.put("chapterList",chapterList);
        //异步记录浏览日志
        BrowsingHistory browsingHistory = new BrowsingHistory();
        browsingHistory.setAppUserId(SecurityUtils.getAppUserId());
        browsingHistory.setBookId(bookId);
        browsingHistory.setCreateTime(DateUtils.getNowDate());
        AsyncManager.me().execute(AsyncFactory.recordBrowsingHistory(browsingHistory));
        return success(result);
    }

    @ApiOperation(value = "获取书籍评论")
    @GetMapping("/getBookComments/{bookId}")
    public TableDataInfo getBookComments(@PathVariable("bookId") String bookId){
        startPage();
        List<Comment> comments = commentService.list(new LambdaQueryWrapper<Comment>()
                .eq(Comment::getBookId, bookId)
                .orderByDesc(Comment::getCreateTime));
        if(ObjectUtil.isEmpty(comments)){
            return getDataTable(Collections.EMPTY_LIST);
        }
        //查询用户信息
        List<String> userIds = comments.stream().map(Comment::getAppUserId).distinct().collect(Collectors.toList());
        List<AppUser> users = appUserService.listByIds(userIds);
        List<AppUserVo> appUserVos = BeanUtil.copyToList(users, AppUserVo.class);
        Map<String, AppUserVo> userMap = appUserVos.stream().collect(Collectors.toMap(AppUserVo::getId, Function.identity()));
        comments.stream().forEach(item -> item.setUser(userMap.getOrDefault(item.getAppUserId(),null)));
        return getDataTable(comments);
    }


    /**
     * 检查是否关注
     * @param userId
     * @return
     */
    @ApiOperation(value = "检查是否关注,传入被关注人id")
    @GetMapping("/checkFollowStatus/{userId}")
    public AjaxResult checkFollowStatus(@PathVariable("userId") String userId){
    	return AjaxResult.success(ObjectUtil.isNotNull(followersService.getOne(new LambdaQueryWrapper<Followers>()
                .eq(Followers::getFollower, SecurityUtils.getAppUserId())
                .eq(Followers::getFollowedPerson, userId)
                .last("LIMIT 1"))));
    }


    /**
     * 查询浏览记录
     * @return
     */
    @ApiOperation(value = "查询浏览记录")
    @GetMapping("/selectBrowsingHistory")
    public TableDataInfo selectBrowsingHistory(){
        List<BrowsingHistory> list = browsingHistoryService.list(new LambdaQueryWrapper<BrowsingHistory>()
                .eq(BrowsingHistory::getAppUserId, SecurityUtils.getAppUserId())
                .orderByDesc(BrowsingHistory::getCreateTime));
        if(ObjectUtil.isEmpty(list)){
            return getDataTable(list);
        }
        List<String> bookIds = list.stream().map(BrowsingHistory::getBookId).distinct().collect(Collectors.toList());
        List<Book> books = bookService.listByIds(bookIds);
        Map<String, Book> bookMap = books.stream().collect(Collectors.toMap(Book::getId, Function.identity()));
        list.stream().forEach(item -> item.setBook(bookMap.getOrDefault(item.getBookId(),null)));
        return getDataTable(list);
    }


    /**
     * 金币兑换
     * @param exchange
     * @return
     */
    @ApiOperation(value = "金币兑换")
    @RepeatSubmit
    @PutMapping("/goldCoinExchange")
    public AjaxResult goldCoinExchange(@RequestBody @Validated GoldCoinExchangeParam exchange){
        if(exchange.getCount() < 100){
            return error("兑换数量不能小于100");
        }
        //兑换比例 100:1
        int money = exchange.getCount() / 100;
        AppUser user = appUserService.getById(SecurityUtils.getAppUserId());
        if(ObjectUtil.isNotNull(user)){
            if(user.getGoldCoin() < exchange.getCount()){
                return error("金币不足");
            }
            user.setWallet(user.getWallet().add(new BigDecimal(money)));
            user.setGoldCoin(user.getGoldCoin()-exchange.getCount());
            appUserService.updateById(user);
        }
        return success();
    }


    /**
     * 查询书架里面的书籍信息
     * @param bookShelf
     * @return
     */
    @ApiOperation(value = "查询书架里面的书籍信息")
    @GetMapping("/selectBookShelfList")
    public TableDataInfo selectBookShelfList(BookShelf bookShelf){
        bookShelf.setAppUserId(SecurityUtils.getAppUserId());
        List<BookShelf> list = bookShelfService.list(new LambdaQueryWrapper<BookShelf>()
                .eq(BookShelf::getAppUserId, bookShelf.getAppUserId())
                .orderByDesc(BookShelf::getCreateTime));
        if(ObjectUtil.isEmpty(list)){
            return getDataTable(Collections.EMPTY_LIST);
        }
        List<String> bookIds = list.stream().map(BookShelf::getBookId).distinct().collect(Collectors.toList());
        List<Book> books = bookService.listByIds(bookIds);
        Map<String, Book> bookMap = books.stream().collect(Collectors.toMap(Book::getId, Function.identity()));
        list.stream().forEach(item -> item.setBook(bookMap.getOrDefault(item.getBookId(),null)));
        return getDataTable(list);
    }

    /**
     * 加入书籍到书架
     * @param bookShelf
     * @return
     */
    @ApiOperation(value = "加入书籍到书架")
    @RepeatSubmit
    @PostMapping("/addBookShelf")
    public AjaxResult addBookShelf(@RequestBody @Validated BookShelf bookShelf){
        //判断是否已经加入了
        BookShelf dbData = bookShelfService.getOne(new LambdaQueryWrapper<BookShelf>()
                .eq(BookShelf::getAppUserId, bookShelf.getAppUserId())
                .eq(BookShelf::getBookId, bookShelf.getBookId())
                .last("LIMIT 1"));
        if(ObjectUtil.isNotNull(dbData)){
            return warn("书籍已经加入书架");
        }
        bookShelf.setAppUserId(SecurityUtils.getAppUserId());
        bookShelf.setCreateBy(SecurityUtils.getAppUsername());
        bookShelf.setCreateTime(DateUtils.getNowDate());
    	return success(bookShelfService.save(bookShelf));
    }


    /**
     * 从书架删除书籍
     * @param bookShelf
     * @return
     */
    @ApiOperation(value = "从书架删除书籍")
    @DeleteMapping("/delBookFromShelf")
    public AjaxResult delBookFromShelf(@RequestBody @Validated BookShelf bookShelf){
    	bookShelf.setAppUserId(SecurityUtils.getAppUserId());
    	return success(bookShelfService.remove(new LambdaQueryWrapper<BookShelf>()
    			.eq(BookShelf::getAppUserId, bookShelf.getAppUserId())
    			.eq(BookShelf::getBookId, bookShelf.getBookId())));
    }
}
